/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package datenbank;

import java.sql.*;
import java.util.Vector;
import data.*;


/**
 *
 * @author Daniel
 */
public class ProduktMapper {

    private static ProduktMapper produktMapper = null;

    /*
     * statische Methode, die sicherstellt, dass nur eine Istanz von ProduktMapper erzeugt wird.
     *
     * @return Das produktMapper -Objekt.
     */
    public static ProduktMapper produktMapper() {
        if (produktMapper == null) {
            produktMapper = new ProduktMapper();
        }

        return produktMapper;
    }

    /**
    * Hier wird ein neues Produkt (-Objekt) in die Datenbank eingefügt.
    * Dabei wird auch überprüft was die bisher höhste produkt_id(der Primärschlüssel) ist.
    *
    * @param pr ist das das zu speichernde Produkt-Objekt
    * @return das bereits übergebene Objekt, jedoch mit ggf. korrigierter produkt_id vom Typ Produkt
    */
    public Produkt insert(Produkt pr) {
        Connection con = DBConnection.connection();

        try {
            Statement stmt = con.createStatement();

            /*
             * Hier wird überprüft welche produkt_id bisher die höhste ist.
             */
            ResultSet rs = stmt.executeQuery(
                    "SELECT MAX(produkt_id) AS maxid " +
                    "FROM Produkt ");


            if (rs.next()) {
                try {
                    /* Hier wird die bisher höhste vorhandene produkt_id um +1 erhöht.
                     */
                    pr.set_produkt_id(rs.getInt("maxid") + 1);

                    stmt = con.createStatement();

                    /* Die tatsächliche Einfügeoperation mit den übergebenden Attributen.
                     */
                    stmt.executeUpdate("INSERT INTO Produkt(produkt_id,bezeichnung,typ,k_beschreibung,preis) " +
                            "VALUES (" +
                            pr.get_produkt_id() + ",'" +
                            pr.get_bezeichnung() + "','" +
                            pr.get_typ() + "','" +
                            pr.get_beschreibung_k() + "'," +
                            pr.get_preis() + ")");                            

                } catch (Exception ex) {
                    ex.printStackTrace();
                }
            }
        } catch (SQLException e2) {
            e2.printStackTrace();
        }
        /* Rückgabe des angelegten Objekts pr von Typ Produkt.
         */
        return pr;
    }

    public Produkt update(Produkt pr) {
        /* Stellt durch Aufruf der connection() Methode der DBConnection-Klasse, die Verbindung zur Datenbank her. */
        Connection con = DBConnection.connection();

        try {
            // Leeres SQL-Statement stmt wird angelegt.
            Statement stmt = con.createStatement();

            //Statement wird ausgefüllt und als Query an die DB geschickt.
            stmt.executeUpdate("UPDATE Produkt " +
                    "SET produkt_id=" + pr.get_produkt_id() + "," +
                    "bezeichnung='" + pr.get_bezeichnung() + "'," +
                    "k_beschreibung='" + pr.get_beschreibung_k() + "'," +
                    "typ='" + pr.get_typ() + "'," +
                    "preis=" + pr.get_preis() + " " +
                    "WHERE produkt_id=" + pr.get_produkt_id());

        } catch (SQLException e2) {
            e2.printStackTrace();
        } catch (Exception e) {
            e.printStackTrace();
        }
        // das als Parameter übergebende Objekt des Typs Produkt wird zurückgegeben
        return pr;
    }

    /**
     * Diese Methode löscht alle Daten eines Produkt- Objekts aus der Datenbank.
     *
     * @param pr ist das zu löschende Objekt
     */
    public void delete(Produkt pr) {
        Connection con = DBConnection.connection();

        try {
            // Leeres SQL-Statement stmt wird angelegt.
            Statement stmt = con.createStatement();

            // Statement wird ausgefüllt und als Query an die DB geschickt.
            stmt.executeUpdate("DELETE FROM Produkt " +
                    "WHERE produkt_id=" + pr.get_produkt_id());

        } catch (SQLException e2) {
            e2.printStackTrace();
        } catch (Exception e) {
            e.printStackTrace();
        }


    }

    /**
     * Bei dieser Methode werden alle Produkte ausgelesen.
     *
     * @return Es wird ein Vektor mit Produkt-Objekten, d.h. allen in der Datenbank angelegte Produkte, zurückgegeben.
     * Bei evtl. Exceptions wird ein partiell gefüllter oder ggf.
     * auch leerer Vektor vom Typ Produkt zurückgeliefert.
     */
    public Vector<Produkt> findAll_getraenke() {
        Connection con = DBConnection.connection();
        Vector<Produkt> result = new Vector<Produkt>();

        try {
            Statement stmt = con.createStatement();

            /*
             * Da Getränke und Speisen in einer Datenbanktabelle abgespeichert werden,
             * werden bei der SELECT- Abfrage nur die Einträge mit dem Datensatz "WHERE Typ= 'g'" für Getränke berücksichtigt.
             */
            ResultSet rs = stmt.executeQuery(
                    "SELECT produkt_id, bezeichnung, typ, beschreibung_k, preis" +
                    "FROM Produkt " + "WHERE Typ='g'" +
                    "ORDER BY bezeichung");

            // Für jeden Eintrag im Suchergebnis wird nun ein Produkt-Objekt pr erstellt.
            while (rs.next()) {
                try {
                    ProduktImpl pr = new ProduktImpl();
                    pr.set_produkt_id(rs.getInt("produkt_id"));
                    pr.set_bezeichnung(rs.getString("bezeichnung"));
                    pr.set_typ(rs.getString("typ"));
                    pr.set_beschreibung_k(rs.getString("k_beschreibung"));
                    pr.set_preis(rs.getDouble("preis"));
                    //Hier wird das Objekt dem Ergebnisvektor hinzugefügt
                    result.addElement(pr);
                } catch (Exception e) {
                    e.printStackTrace();
                    //Bei einer evtl. Exception wird die while-Schleife abgebrochen.
                    break;
                }
            }
        } catch (SQLException e2) {
            e2.printStackTrace();
        }
        // Ergebnisvektor vom Typ Produkt wird zurückgeben.
        return result;
    }


    /**
     * Bei dieser Methode werden alle Produkte ausgelesen.
     *
     * @return Es wird ein Vektor mit Produkt-Objekten, d.h. allen in der Datenbank angelegte Produkte, zurückgegeben.
     * Bei evtl. Exceptions wird ein partiell gefüllter oder ggf.
     * auch leerer Vektor vom Typ Produkt zurückgeliefert.
     */
    public Vector<Produkt> findAll_produkt() {
        Connection con = DBConnection.connection();
        Vector<Produkt> result = new Vector<Produkt>();

        try {
            Statement stmt = con.createStatement();

            /*
             * Da Getränke und Speisen in einer Datenbanktabelle abgespeichert werden,
             * werden bei der SELECT- Abfrage nur die Einträge mit dem Datensatz "WHERE Typ= 'g'" für Getränke berücksichtigt.
             */
            ResultSet rs = stmt.executeQuery(
                    "SELECT produkt_id, bezeichnung, typ, beschreibung_k, preis" +
                    "FROM Produkt " +
                    "ORDER BY bezeichnung");

            // Für jeden Eintrag im Suchergebnis wird nun ein Produkt-Objekt pr erstellt.
            while (rs.next()) {
                try {
                    ProduktImpl pr = new ProduktImpl();
                    pr.set_produkt_id(rs.getInt("produkt_id"));
                    pr.set_bezeichnung(rs.getString("bezeichnung"));
                    pr.set_typ(rs.getString("typ"));
                    pr.set_beschreibung_k(rs.getString("k_beschreibung"));
                    pr.set_preis(rs.getDouble("preis"));
                    //Hier wird das Objekt dem Ergebnisvektor hinzugefügt
                    result.addElement(pr);
                } catch (Exception e) {
                    e.printStackTrace();
                    //Bei einer evtl. Exception wird die while-Schleife abgebrochen.
                    break;
                }
            }
        } catch (SQLException e2) {
            e2.printStackTrace();
        }
        // Ergebnisvektor vom Typ Produkt wird zurückgeben.
        return result;
    }

    public Vector<Produkt> findAll_speisen() {
        Connection con = DBConnection.connection();
        Vector<Produkt> result = new Vector<Produkt>();

        try {
            Statement stmt = con.createStatement();

            /*
             * Da Getränke und Speisen in einer Datenbanktabelle abgespeichert werden,
             * werden bei der SELECT- Abfrage nur die Einträge mit dem Datensatz "WHERE Typ= 's'" für Speisen berücksichtigt.
             */
            ResultSet rs = stmt.executeQuery(
                    "SELECT produkt_id, bezeichnung, typ, beschreibung_k, preis" +
                    "FROM Produkt " + "WHERE Typ='s'" +
                    "ORDER BY bezeichnung");

            // Für jeden Eintrag im Suchergebnis wird nun ein Produkt-Objekt pr erstellt.
            while (rs.next()) {
                try {
                    ProduktImpl pr = new ProduktImpl();
                    pr.set_produkt_id(rs.getInt("produkt_id"));
                    pr.set_bezeichnung(rs.getString("bezeichnung"));
                    pr.set_typ(rs.getString("typ"));
                    pr.set_beschreibung_k(rs.getString("k_beschreibung"));
                    pr.set_preis(rs.getDouble("preis"));
                    //Hier wird das Objekt dem Ergebnisvektor hinzugefügt
                    result.addElement(pr);

                } catch (Exception e) {
                    e.printStackTrace();
                    //Bei einer evtl. Exception wird die while-Schleife abgebrochen.
                    break;
                }
            }
        } catch (SQLException e2) {
            e2.printStackTrace();
        }
        // Ergebnisvektor vom Typ Produkt wird zurückgeben.
        return result;
    }

    /**
     * Diese Methode sucht die Datenbank nach einem Produkt mit eingegebener ID.
     *
     * @param produkt_id ist das Primärschlüsselattribut Produkt in der Datenbank.
     * @return Das Objekt vom Typ Produkt, das der id entspricht wird zurückgegebn.
     * null wird zurückgegeben, wenn das Objekt nicht in der Datenbank vorhanden ist.
     * Da es sich um einen Primärschlüssel handelt und dieser somit eindeutig ist, wird genau ein Objekt zurückgegeben.
     */
    public Produkt findbyid(int id) {
        Connection con = DBConnection.connection();

        try {
            Statement stmt = con.createStatement();
            /*
             * Da Baugruppen, Bauteile und Enderzeugnisse in einer Datenbanktabelle abgespeichert werden,
             * werden bei der SELECT- Abfrage nur die Einträge mit dem Datensatz "WHERE Typ= 't'" für Bauteil berücksichtigt.
             */
            ResultSet rs = stmt.executeQuery(
                    "SELECT produkt_id, bezeichnung, typ, k_bezeichnung, preis FROM Produkt " +
                    "WHERE produkt_id =" + id +
                    " ORDER BY produkt_id");

            /*
             * Es wird geprüft, ob ein Ergebnis vorliegt. Wenn ja werden die Attribute produkt_id,
             * bezeichnung, typ, k_bezeichnung und preis ausgelesen und als Typ Produkt zurückgegeben.
             */
            if (rs.next()) {
                try {

                    Produkt pr = new ProduktImpl();
                    pr.set_produkt_id(rs.getInt("produkt_id"));
                    pr.set_bezeichnung(rs.getString("bezeichnung"));
                    pr.set_typ(rs.getString("typ"));
                    pr.set_beschreibung_k(rs.getString("k_beschreibung"));
                    pr.set_preis(rs.getDouble("preis"));
                    return pr;

                } catch (Exception e) {
                    e.printStackTrace();
                    return null;
                }
            }
        } catch (SQLException e2) {
            e2.printStackTrace();
            return null;
        }

        return null;
    }

    /**
     * Diese Methode sucht die Datenbank nach einem Produkt mit eingegebenen Namen.
     *
     * @param name ist der name der gefunden werden soll
     * @return Das Objekt vom Typ Produkt, das dem namen entspricht wird zurückgegebn.
     * null wird zurückgegeben, wenn das Objekt mit dem übergebenen Namen nicht in der Datenbank vorhanden ist.
     * Da der Name, wie der Primärschlüssel eindeutig ist, wird genau ein Objekt zurückgegeben.
     */
    public Produkt findbybezeichnung(String bezeichnung) {
        Connection con = DBConnection.connection();

        try {
            Statement stmt = con.createStatement();
            /*
             * Da Baugruppen, Bauteile und Enderzeugnisse in einer Datenbanktabelle abgespeichert werden,
             * werden bei der SELECT- Abfrage nur die Einträge mit dem Datensatz "WHERE Typ= 't'" für Bauteil berücksichtigt.
             */
            ResultSet rs = stmt.executeQuery(
                    "SELECT produkt_id, bezeichnung, typ, k_bezeichnung, preis FROM Produkt " +
                    "WHERE bezeichnung ='" + bezeichnung +
                    "'");

            /*
             * Es wird geprüft, ob ein Ergebnis vorliegt. Wenn ja werden die Attribute produkt_id,
             * bezeichnung, typ, k_bezeichnung und preis ausgelesen und als Typ Produkt zurückgegeben.
             */
            if (rs.next()) {
                try {

                    Produkt pr = new ProduktImpl();
                    pr.set_produkt_id(rs.getInt("produkt_id"));
                    pr.set_bezeichnung(rs.getString("bezeichnung"));
                    pr.set_typ(rs.getString("typ"));
                    pr.set_beschreibung_k(rs.getString("k_beschreibung"));
                    pr.set_preis(rs.getDouble("preis"));
                    return pr;

                } catch (Exception e) {
                    e.printStackTrace();
                    return null;
                }
            }
        } catch (SQLException e2) {
            e2.printStackTrace();
            return null;
        }

        return null;
    }
}
